package com.cellulam.framework.core.rest;

import com.fasterxml.jackson.core.type.TypeReference;
import com.cellulam.framework.core.model.DataResult;
import com.cellulam.framework.core.utils.JacksonUtils;
import com.cellulam.framework.core.exceptions.BusinessException;
import com.cellulam.framework.core.exceptions.SystemErrorStatus;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.Callable;

public class RestClient extends RestTemplate {

    public RestClient(int timeout) {

        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(timeout);
        httpRequestFactory.setConnectTimeout(timeout);
        httpRequestFactory.setReadTimeout(timeout);

        this.setRequestFactory(httpRequestFactory);
//        this.getInterceptors().add(new JsonMimeInterceptor());
    }

    public RestClient() {
    }

    /**
     * 返回 reference 对象
     *
     * @param url
     * @param reference
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T getForObject(String url, TypeReference<T> reference, Object... uriVariables) {
        String json = super.getForObject(url, String.class, uriVariables);
        if (StringUtils.isEmpty(json)) {
            return null;
        }

        return JacksonUtils.toObjByReference(json, reference);
    }

    /**
     * 返回data数据，status不等于0时，抛出业务异常
     *
     * @param url
     * @param tClass
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T getForResult(String url, Class<T> tClass, Object... uriVariables) {
        return this.callForResult(() -> this.getForObject(url, String.class, uriVariables), tClass);
    }

    /**
     * 返回reference对象
     *
     * @param url
     * @param request
     * @param reference
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T postForObject(String url, Object request, TypeReference<T> reference, Object... uriVariables) {
        String json = super.postForObject(url, request, String.class, uriVariables);
        if (StringUtils.isEmpty(json)) {
            return null;
        }

        return JacksonUtils.toObjByReference(json, reference);
    }


    /**
     * 返回data数据，status不等于0时，抛出业务异常
     *
     * @param url
     * @param request
     * @param tClass
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T postForResult(String url, Object request, Class<T> tClass, Object... uriVariables) {
        return this.callForResult(() -> this.postForObject(url, request, String.class, uriVariables), tClass);
    }

    private <T> T callForResult(Callable<String> callable, Class<T> tClass) {
        try {
            String json = callable.call();
            DataResult<T> result = JacksonUtils.toObjByNestRef(json, DataResult.class, tClass);
            if (result.isOk()) {
                return result.getData();
            }

            throw new BusinessException(result.getStatus(), result.getMessage());
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException(SystemErrorStatus.API_CALL_FAIL, e);
        }
    }
}
